<?php

class S_Model extends CI_Model {
	
	//真实的表名称，不包括数据表前缀，可继承类修改（建议在继承类中定义好）
	protected $table = '';
	
	//表的主键字段名称
	protected $primary_key = '';
	
	//表字段数组，第一个为主键
	protected $fields = array();
	
	//结果中记录行数
	protected $_num_rows = 0;
	
	public function __construct()
	{
		parent::__construct();
		
		$class = get_class($this);
		
		if ($class!='S_Model')
		{
			$this->init();
		}
		
		log_message('debug', '成功加载模型类');
	}
	
	/*
	 * 数据初始化，表名称，表字段，主键名
	 */
	protected function init()
	{
		//表名称
		if (trim($this->table)=='')
		{
			$class = get_class($this);
			if(preg_match('/^(.*)_model$/', $class, $match))
			{
				$this->table = strtolower($match[1]);
			}
			else
			{
				show_error('模型名称 '.$class.' 错误');
			}
		}
		
		//字段信息
		if (defined('ENVIRONMENT') && strtolower(ENVIRONMENT)=='production')
		{
			$need_cache = TRUE;
			$this->load->library('cache');
			$fields =  $this->cache->get($this->table.'_fileds_cache');
			if (FALSE!==$fields)
			{
				$this->primary_key = current($fields);
				$this->fields = $fields;
				exit();
			}
		}
		
		if ( ! isset($fields) || FALSE===$fields)
		{
			$datas = $this->db->field_data($this->table);
			$fields = array();
			if ($datas)
			{
				foreach ($datas as $data)
				{
					if ($data->primary_key==1)
					{
						$this->primary_key = $data->name;
					}
					$fields[$data->name] = (array)$data;
				}
				$fields = array_merge(array($this->primary_key=>''), $fields);
			}
		}
		
		$this->fields = $fields;
		if (isset($need_cache))
		{
			$this->cache->set($this->table.'_fileds_cache', 3600*24*30);
		}
	}
	
	/*
	 * 返回模型表名称
	 */
	public function table()
	{
		return $this->table;
	}
	
	/*
	 * 返回主键字段名称
	 */
	public function primary_key()
	{
		return $this->primary_key;
	}
	
	/*
	 * 返回模型表字段数组
	 */
	public function fields()
	{
		return array_keys($this->fields);
	}
	
	/*
	 * 新插入记录的主键值
	 */
	public function insert_id()
	{
		return $this->db->insert_id();
	}
	
	/*
	 * 当执行写入操作（insert,update等）的查询后，显示被影响的行数。
	 */
	public function affect_rows()
	{
		return $this->db->affect_rows();
	}
	
	/*
	 * 返回查询语句返回记录行数
	 */
	public function num_rows()
	{
		return $this->_num_rows;
	}
	
	/*
	 * 最后条执行的语句
	 */
	public function last_query()
	{
		return $this->db->last_query();
	}
	
	/*
	 * 组建插入语句
	 * data	数据，数组
	 */
	public function insert_string($data)
	{
		return $this->db->insert_string($this->table, $data);	
	}
	
	/*
	 * 组建更新语句
	 * data	数据，数组
	 * condition	条件，数组
	 */
	public function update_string($data, $condition)
	{
		return $this->db->update_string($this->table, $data, $condition);
	}

	/*
	 * 执行sql语句
	 * sql	为原始sql语句
	 * binds	可以绑定sql的字段值，比如$sql = "select * from user where a = ? and b = ?" $binds = array(1, 'haha') 会自动转换数据类型的
	 */
	public function query($sql, $binds = FALSE)
	{
		$query = $this->db->query($sql, $binds, TRUE);
		$this->num_rows = $query->num_rows();
		return $query;
	}

	/*
	 * 统计，若不存在条件，直接统计这个表
	 * condition	条件，数组
	 */
	public function get_count($condition = NULL)
	{
		if ( ! isset($condition))
		{
			return $this->db->count_all($this->table);
		}
		
		$result = $this->db->select('count(*) as count')->from($this->table)->where($condition)->get()->row_array();
		return intval($result['count']);
	}
	
	/*
	 * 根据条件判断是否存在，存在返回TRUE，失败返回FALSE
	 * condition	条件
	 */
	public function exist($condition)
	{
		if (NULL!==$condition)
		{
			if ( ! is_array($condition) && is_numeric($condition))
			{
				$condition = array(
					$this->primary_key => $condition
				);
			}
		}
		return ($this->db->select('id')->from($this->table)->where($condition)->limit(1)->get()->row_array()) ? TRUE : FALSE;
	}
	
	/*
	 * 根据主键返回记录
	 * id	主键值
	 * fields	要返回的字段，字符串
	 */
	public function get($id, $fields = '*')
	{
		$fields = $fields=='*' ? implode(',', array_keys($this->fields)) : $fields;
		$query = $this->db->select($fields)->from($this->table)->where($this->primary_key, $id)->limit(1)->get();
		$this->_num_rows = $query->num_rows();
		return $query->row_array();
	}
	
	/*
	 * 根据条件查询一条记录的某个字段信息
	 * name	字段名称，字符串
	 * condition 条件
	 * 不存在返回false
	 */
	public function get_field($name, $condition = NULL)
	{
		if (NULL!==$condition)
		{
			if ( ! is_array($condition) && is_numeric($condition))
			{
				$condition = array(
					$this->primary_key => $condition
				);
			}
		}

		if ( ! in_array($name, array_keys($this->fields)))
		{
			return FALSE;
		}
		$this->db->select($name)->from($this->table);
		if(NULL!==$condition)
		{
			$this->db->where($condition);
		}
		$query = $this->db->limit(1)->get();
		$this->_num_rows = $query->num_rows();
		$result = $query->row_array();
		return current($result);
	}

	/*
	 * 根据条件返回一条数据
	 * condition	条件
	 * fields	要返回的字段，字符串
	 */
	public function get_one($condition = array(), $fields = '*')
	{
		if (NULL!==$condition)
		{
			if ( ! is_array($condition) && is_numeric($condition))
			{
				$condition = array(
					$this->primary_key => $condition
				);
			}
		}
		$fields = $fields=='*' ? implode(',', array_keys($this->fields)) : $fields;
		$query = $this->db->select($fields)->from($this->table)->where($condition)->limit(1)->get();
		$this->_num_rows = $query->num_rows();
		return $query->row_array();
	}
	
	/*
	 * 返回多条记录
	 * condition	数组条件，数组
	 * fields	要返回的字段，字符串
	 * order	排序,默认主键升序，字符串
	 * start	从哪行开始，整数
	 * limit	返回条数，整数
	 */
	public function get_list($condition = array(), $fields = '*', $order = '', $start = 0, $limit = 10)
	{
		$fields = $fields=='*' ? implode(',', array_keys($this->fields)) : $fields;
		$order = trim($order);
		$order = $order ? $order : ($this->primary_key.' ASC');
		$query = $this->db->select($fields)->from($this->table)->where($condition)->order_by($order)->limit($limit, $start)->get();
		$this->_num_rows = $query->num_rows();
		return $query->result_array();
	}
	
	/*
	 * 根据条件返回所有
	 */
	public function get_all($condition = array(), $fields = '*', $order = '')
	{
		$fields = $fields=='*' ? implode(',', array_keys($this->fields)) : $fields;
		$order = trim($order);
		$order = $order ? $order : ($this->primary_key.' ASC');
		$query = $this->db->select($fields)->from($this->table)->where($condition)->order_by($order)->get();
		$this->_num_rows = $query->num_rows();
		return $query->result_array();
	}
	
	/*
	 * 返回分页数据
	 * p	当前页，整数
	 * per_page	每页显示多少数据，整数
	 * conditon	条件，数组
	 */
	public function get_page($p, $per_page = 10, $condition = array())
	{
		return $this->get_list($condition, '*', $this->primary_key.' DESC', ($p-1)*$per_page, $per_page);
	}
	
	/*
	 * 插入数据
	 * data	数据，数组
	 * 失败返回FALSE，成功返回插入的id
	 */
	public function insert($data)
	{
		//检测不存在的字段
		if ($data)
		{
			foreach($data as $key => $value)
			{
				if( ! in_array($key, array_keys($this->fields)))
				{
					log_message('error', '模型'.$this->table.'不存在字段'.$key);
					unset($data[$key]);
				}
			}
		}
		
		if (FALSE===$this->db->insert($this->table, $data))
		{
			return FALSE;
		}

		return $this->db->insert_id();
	}
	
	/*
	 * 修改数据
	 * data	数据，数组
	 * condition	条件，数组
	 * 成功返回修改的记录数，失败返回false
	 */
	public function update($data, $condition = NULL)
	{
		if (NULL!==$condition)
		{
			if ( ! is_array($condition) && is_numeric($condition))
			{
				$condition = array(
					$this->primary_key => $condition
				);
			}
		}

		if (FALSE===$this->db->update($this->table, $data, $condition))
		{
			return FALSE;
		}
		return $this->db->affected_rows();
	}
	
	/*
	 * 根据条件删除记录
	 * 失败返回FALSE，成功返回删除的记录条数
	 * 例如：delete(1)或者delete(数组形式的where条件)
	 */
	public function delete($condition)
	{	
		if (NULL!==$condition)
		{
			if ( ! is_array($condition) && is_numeric($condition))
			{
				$condition = array(
					$this->primary_key => $condition
				);
			}
		}

		if (FALSE===$this->db->delete($this->table, $condition))
		{
			return FALSE;
		}
		return $this->db->affected_rows();
	}
	
}